#include "Buffer.h"
#include "Lock.h"
#include <iostream>
Buffer::Buffer(void) 
	: 
	m_data(new char[DEFAULT_BUFFER_SIZE]), 
	m_size(DEFAULT_BUFFER_SIZE), 
	m_readPos(0), 
	m_writePos(0)
{
	InitializeCriticalSection(&m_criticalSection);
}	
Buffer::Buffer(Buffer const& rhs)
	:
	m_data(new char[rhs.m_size]),
	m_size(rhs.m_size),
	m_readPos(rhs.m_readPos),
	m_writePos(rhs.m_writePos),
	m_criticalSection(rhs.m_criticalSection)
{
	memcpy(m_data, rhs.m_data, m_writePos);
}
Buffer::~Buffer(void)
{
	delete[] m_data;
	DeleteCriticalSection(&m_criticalSection);
}
char& Buffer::operator[](size_t pos) const
{
	Lock lock(m_criticalSection);
	return m_data[m_readPos + pos];
}
Buffer& Buffer::operator=(Buffer const& rhs)
{
	if (this != &rhs)
	{
		if (m_data)
			delete[] m_data;
		m_size = rhs.m_size;
		m_readPos = rhs.m_readPos;
		m_writePos = rhs.m_writePos;
		m_criticalSection = rhs.m_criticalSection;
		m_data = new char[m_size];
		memcpy(m_data, rhs.m_data, m_writePos);
	}
	return *this;
}
Buffer::operator int(void) const
{
	Lock lock(m_criticalSection);

	int num = 0;
	num = *reinterpret_cast<int*>(m_data + m_readPos);
	return num;
}
bool Buffer::Read(char* const buff, size_t len)
{
	Lock lock(m_criticalSection);

	if (len > m_writePos - m_readPos)
	{
		memset(buff, 0, len);
		return false;
	}
	memcpy(buff, m_data + m_readPos, len);
	m_readPos += len;

	if (m_readPos >= m_writePos)
	{
		if (m_size > DEFAULT_BUFFER_SIZE)
		{
			std::cout << "Reseting to default size from " << m_size << std::endl;
			delete[] m_data;

			m_data = new char[DEFAULT_BUFFER_SIZE];
			m_size = DEFAULT_BUFFER_SIZE;
		}
		m_readPos = 0;
		m_writePos = 0;
	}
	return true;
}
bool Buffer::Append(char const* const buff, size_t len)
{
	Lock lock(m_criticalSection);

	while (m_writePos + len > m_size)
	{
		size_t newSize = m_size * 2;
		char* newData = new char[newSize];

		memcpy(newData, m_data, m_writePos);
		delete[] m_data;

		m_data = newData;
		m_size = newSize;

		std::cout << "Increasing size to " << m_size << std::endl;
	}
	
	memcpy(m_data + m_writePos, buff, len);
	m_writePos += len;
	return true;
}
size_t Buffer::GetSize(void) const
{
	Lock lock(m_criticalSection);
	return m_writePos - m_readPos;
}